/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package deatax.display.particle;

import deatax.display.Texture;
import javax.media.opengl.GL2;

/**
 *
 * @author nrechten
 */
public class ParticleSpawn {

    public static int WORD;

    float[] particles;
    ParticleRule[] rules;
    int word = 5;
    float[] position;

    int maxParticles;
    int max;
    float spawnrate;
    float lifespan;
    float randomness;

    int count = 0;
    int offset = 0;

    float spawnTimer;

    public static float[] screen_normal = new float[]{};
    
    Texture texture;

    public ParticleSpawn(float[] position, int maxParticles, float spawnrate, float lifespan, float randomness, ParticleRule[] rules, Texture t){
        this.position = position;
        if(rules != null){
            for (int i = 0; i < rules.length; i++) {
                word += rules[i].spaceRequirement();
            }
            this.rules = rules;
        }
        particles = new float[maxParticles*word];
        this.maxParticles = maxParticles;
        this.max = maxParticles*word;
        this.spawnrate = spawnrate;
//        this.spawnTimer = spawnrate;
        this.randomness = randomness;
        this.lifespan = lifespan;
        this.texture = t;
    }

    public synchronized void  draw(float scale, GL2 gl){
        //Check if any particles have just died
        for(; count > 0; offset+=word){
            if(offset >= maxParticles * word) offset = 0;
            if(particles[offset]-scale > lifespan){
                count--;
            } else {
                break;
            }
        }

        //Age the particles
        for(int i = 0; i < count; i++){
            particles[(offset + i*word)%max]+=scale;
        }

        spawnTimer += scale;
//        System.out.println(spawnTimer + " + " + scale);
        //Add any new particles
        for(int pindex = 0; spawnTimer > spawnrate; spawnTimer -= spawnrate - (float)(Math.random() * randomness * spawnrate)){
            pindex = (offset + count*word)%max;
            particles[pindex]=0;
            particles[pindex+1]=position[0];
            particles[pindex+2]=position[1];
            particles[pindex+3]=position[2];

            for(int o = 4, i = 0; i < rules.length; i++){
                rules[i].init(particles,pindex+o);
                o += rules[i].spaceRequirement();
            }
            if(count < maxParticles){
                count++;
//                System.out.println("New particle spawned = " + spawnTimer + " scale: " + scale*1000);
            } else {
//                System.out.println("New particle spawned - at max");
                offset+=word;
            }
            
        }

        //Run each rule on each alive particle
        float[] particle = new float[3];
        float modelview[] = new float[16];
        gl.glGetFloatv(gl.GL_MODELVIEW_MATRIX, modelview, 0);

        
        if(texture != null){
            texture.bind(gl);
            gl.glEnable(GL2.GL_TEXTURE_2D);
        }
        
        for(int i = 0, pindex = 0; i < count; i++){
            pindex = (offset + i*word)%max;
            
            particle[0] = 0;
            particle[1] = particle[2] = 1f;

            
            for(int r = 0, o = 4; r < rules.length; r++){
                rules[r].apply(particles, pindex, pindex+o, scale, particle, particles[pindex]);
                o += rules[r].spaceRequirement();
            }
//            System.out.println("Age:" + particles[pindex] + ", Location: (" + particles[pindex+1] + "," + particles[pindex+2] + "," + particles[pindex+3] +")");

            gl.glPointSize(particle[2]);
            gl.glColor4f(1, 1, 1, particle[1]);

            gl.glBegin(GL2.GL_TRIANGLE_FAN);
            gl.glTexCoord2f(0, 0);
            gl.glVertex3f(particles[pindex+1]+(modelview[1]+modelview[0])*particle[2],particles[pindex+2]+(modelview[5]+modelview[4])*particle[2],particles[pindex+3]+(modelview[9]+modelview[8])*particle[2]);
            
            gl.glTexCoord2f(0, 1);
            gl.glVertex3f(particles[pindex+1]+(modelview[1]-modelview[0])*particle[2],particles[pindex+2]+(modelview[5]-modelview[4])*particle[2],particles[pindex+3]+(modelview[9]-modelview[8])*particle[2]);
            
            gl.glTexCoord2f(1, 1);
            gl.glVertex3f(particles[pindex+1]-(modelview[1]+modelview[0])*particle[2],particles[pindex+2]-(modelview[5]+modelview[4])*particle[2],particles[pindex+3]-(modelview[9]+modelview[8])*particle[2]);
            
            gl.glTexCoord2f(1, 0);
            gl.glVertex3f(particles[pindex+1]+(-modelview[1]+modelview[0])*particle[2],particles[pindex+2]+(-modelview[5]+modelview[4])*particle[2],particles[pindex+3]+(-modelview[9]+modelview[8])*particle[2]);
            gl.glEnd();
        }

        if(texture != null){

            gl.glDisable(GL2.GL_TEXTURE_2D);
        }
    }

//    float[] l3dBillboardGetUpRightVector(GL2 gl, float[] up,float[] right) {
//
//	float modelview[] = gl.glGetFloatv(gl.GL_MODELVIEW_MATRIX, modelview, 0);
//
//	right[0] = modelview[0];
//	right[1] = modelview[4];
//	right[2] = modelview[8];
//
//	up[0] = modelview[1];
//	up[1] = modelview[5];
//	up[2] = modelview[9];
//        return
//    }


}
